package core.models;

import java.util.AbstractList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Scanner;

import javax.swing.DefaultListModel;

import org.apache.commons.lang3.StringUtils;

public class DhcpSubnet extends DefaultListModel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -876134191476010956L;
	private String network;
	private String netmask;
	private HashMap<String, String> options;
	private List<DhcpClient> clients;

	private static final String OPTION_REGEX = "^\\s*((option\\s+)?[\\w\\-]+)\\s+(.+);\\s*";
	private static final String CLIENT_REGEX = "^\\s*host\\s+[\\w\\-]+\\s+\\{\\s*";
	private static final String END_REGEX = "^\\s*}\\s*";

	public DhcpSubnet(String network, String netmask) {
		this.network = network;
		this.netmask = netmask;
		options = new HashMap<String, String>();
		clients = new AbstractList<DhcpClient>() {

			@Override
			public DhcpClient get(int index) {
				return (DhcpClient) getElementAt(index);
			}

			@Override
			public int size() {
				return getSize();
			}
		};
	}

	public String getNetwork() {
		return network;
	}

	public void setNetwork(String network) {
		this.network = network;
	}

	public String getNetmask() {
		return netmask;
	}

	public void setNetmask(String netmask) {
		this.netmask = netmask;
	}

	public void processConfig(Scanner scanner) {
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			if (line.matches(OPTION_REGEX)) {
				String[] option = line.trim().split("\\s+");
				if (option[0].equals("option")) {
					options.put(option[0] + " " + option[1],
							StringUtils.chop(StringUtils.join(option, " ", 2, option.length)));
				} else {
					options.put(option[0],
							StringUtils.chop(StringUtils.join(option, " ", 1, option.length)));
				}
			} else if (line.matches(CLIENT_REGEX)) {
				String[] clientOptions = line.trim().split("\\s+");
				DhcpClient client = new DhcpClient(clientOptions[1]);
				client.processConfig(scanner);
				addElement(client);
			} else if (line.matches(END_REGEX)) {
				break;
			}
		}
	}

	@Override
	public String toString() {
		return network + "/" + netmask;
	}
	
	public String toConfigFormat() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("subnet ");
		buffer.append(this.network);
		buffer.append(" netmask ");
		buffer.append(this.netmask);
		buffer.append(" {\n");
		
		// Options
		for (Entry<String, String> entry : options.entrySet()) {
			buffer.append("   ");
			buffer.append(entry.getKey());
			buffer.append(" ");
			buffer.append(entry.getValue());
			buffer.append(";\n");
		}
		
		buffer.append("\n");
		
		// Clients
		for (DhcpClient client : clients) {
			buffer.append(client.toConfigFormat());
		}
		
		buffer.append("}\n\n");
		return buffer.toString();
	}

	public HashMap<String, String> getOptions() {
		return options;
	}

	public void setOptions(HashMap<String, String> options) {
		this.options = options;
	}

	public void addOption(String key, String value) {
		this.options.put(key, value);
	}
	
	public void setClients(List<DhcpClient> clients) {
		clear();
		for (DhcpClient client : clients) {
			addElement(client);
		}
	}
	
	public List<DhcpClient> getClients() {
		return clients;
	}
}
